class_name AIBehaviorField
extends AIBehavior

const SPREAD_ASSIT_FACTOR := 0.8
const SHOOT_DISTANCE := 150
const SHOOT_PROBABILITY := 0.3
const TACKLE_DISTANCE := 15
const TACKLE_PROBABILITY := 0.3
const PASS_PROBABLILITY := 0.05

func process_ai_movement() -> void:
	var total_force := Vector2.ZERO
	if player.has_ball():
		total_force += get_carrier_steering_force()
	elif is_ball_carried_by_teammate():
		total_force += get_assit_formation_steering()
	else:
		total_force += get_onduty_steering_force()
		if total_force.length_squared() < 1:
			if is_ball_possessed_by_opponent():
				total_force += get_spawn_steering_force()
			elif ball.carried == null:
				total_force += get_ball_proximity_steering_force()
				total_force += get_density_around_ball_steering_force()
			
	total_force = total_force.limit_length(1.0)
	player.velocity = total_force * player.speed
	
func process_ai_decision() -> void:
	if randf() < TACKLE_PROBABILITY and player.position.distance_to(ball.position) < TACKLE_DISTANCE and is_ball_possessed_by_opponent():
		player.switch_states(Player.State.TACKLING)
	if ball.carried == player:
		var target := player.target_goal.get_center_target_position()
		if randf() < SHOOT_PROBABILITY and player.position.distance_to(target) < SHOOT_DISTANCE:
			player.face_towards_target_goal()
			var direction := player.position.direction_to(player.target_goal.get_random_target_position())
			var data := PlayerStateData.build().set_power(player.power).set_shoot_direction(direction)
			player.switch_states(Player.State.SHOOTING, data)
		elif randf() < PASS_PROBABLILITY and has_opponent_nearby() and has_teammate_in_view():
			player.switch_states(Player.State.PASSING)
	
func get_onduty_steering_force() -> Vector2:
	return player.weight_on_duty_steering * player.position.direction_to(ball.position)
	
func get_carrier_steering_force() -> Vector2:
	var target := player.target_goal.get_center_target_position()
	var direction := player.position.direction_to(target)
	var weight := get_bicircular_weight(player.position, target, 100, 0, 150, 1)
	return weight * direction
	
func get_assit_formation_steering() -> Vector2:
	var spawn_difference := ball.carried.spawn_position - player.spawn_position
	var assist_destination := ball.carried.position - spawn_difference * SPREAD_ASSIT_FACTOR
	var direction := player.position.direction_to(assist_destination)
	var weight := get_bicircular_weight(player.position, assist_destination, 30, 0.2, 60, 1)
	return weight * direction
	
func get_ball_proximity_steering_force() -> Vector2:
	var weight := get_bicircular_weight(player.position, ball.position, 50, 1, 120, 0)
	var direction := player.position.direction_to(ball.position)
	return weight * direction
	
func get_spawn_steering_force() -> Vector2:
	var weight := get_bicircular_weight(player.position, player.spawn_position, 30, 0, 100, 1)
	var direction := player.position.direction_to(player.spawn_position)
	return weight * direction
	
func get_density_around_ball_steering_force() -> Vector2:
	var nb_teammate_count := ball.get_proximity_teamate_count(player.country)
	if nb_teammate_count == 0:
		return Vector2.ZERO
	var weight :=  1 - 1.0 / nb_teammate_count
	var direction := ball.position.direction_to(player.position)
	return weight * direction
